#include <QtCore>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "CommFunc.h"

//---------------------------------------------------------------------------------------
#define LINE_LEN 1024
//---------------------------------------------------------------------------------------
static void parse(QFile &infile, QFile &outfile,
                  uint32_t min_addr, int scan, uint32_t *max, uint32_t *min)
{
	int i, j;
	char line[LINE_LEN] = "";
	uint32_t address;
	int rec_type, addr_bytes, byte_count;
	uint8_t c;
    char buf[32];

	do
	{
        infile.readLine(line, LINE_LEN);

		if (line[0] == 'S')								/* an S-record */
		{
			rec_type = line[1] - '0';

			if ((rec_type >= 1) && (rec_type <= 3))		/* data record */
			{
				address = 0;
				addr_bytes = rec_type + 1;

				for (i = 4; i < (addr_bytes * 2) + 4; i++)
				{
					c = line[i];
					address <<= 4;
					address += char_to_uint(c);
				}

				byte_count = (char_to_uint(line[2]) << 4) + char_to_uint(line[3]);
				byte_count -= (addr_bytes + 1);

				if (scan)
				{
					if (*min > address)
						*min = address;

					if (*max < (address + (byte_count - 1)))
						*max = address + (byte_count - 1);
				}
				else
				{
					address -= min_addr;

					j = 0;
					for (i = (addr_bytes * 2) + 4; i < (addr_bytes * 2) + (byte_count * 2) + 4; i += 2)
					{
						buf[j] = (char_to_uint(line[i]) << 4) + char_to_uint(line[i+1]);
						j++;
					}
                    outfile.seek(address);
                    outfile.write(buf, byte_count);
				}
			}
		}
	}
    while(!infile.atEnd());

    infile.seek(0);
}
//---------------------------------------------------------------------------------------
/*
 * min_addr: Start address offset (hex), default = 0.
 * max_addr: Minimum binary file size (hex), default = 0.
 * filler:   Filler byte (hex), default = FF.
 */
int ConvertS19ToBin(const QString &infilename, const QString &outfilename,
            uint32_t &startAddr, size_t max_addr, uint8_t filler)
{
	uint32_t i;
	uint32_t blocks, remain;
	uint32_t pmax = 0;
	uint32_t pmin = 0xffffffff;

    char buf[32];

    QFile infile(infilename), outfile(outfilename);

    if (!infile.open(QFile::ReadOnly))
        goto out;
    if (!outfile.open(QFile::WriteOnly))
        goto out;

    parse(infile, outfile, startAddr, true, &pmax, &pmin);

    startAddr = min(startAddr, pmin);
    max_addr = max(pmax, startAddr + max_addr);

    blocks = (max_addr - startAddr + 1) / 32;
    remain = (max_addr - startAddr + 1) % 32;

    memset(buf, filler, sizeof(buf));
    for (i = 0; i < blocks; i++)
        outfile.write(buf, 32);
    outfile.write(buf, remain);

    parse(infile, outfile, startAddr, false, &pmax, &pmin);

out:
    infile.close();
    outfile.close();
	return(0);
}
//---------------------------------------------------------------------------------------
